import tkinter as tk
from tkinter import ttk, filedialog, messagebox
import os
import subprocess
import threading


class M4sMergerApp:
    def __init__(self, root):
        self.root = root
        self.root.title("m4s视频音频合并提取器")
        self.root.geometry("600x400")
        self.root.resizable(True, True)

        # 文件路径变量
        self.video_path = tk.StringVar()
        self.audio_path = tk.StringVar()
        self.output_path = tk.StringVar()

        # 创建界面
        self.create_widgets()

    def create_widgets(self):
        # 主框架
        main_frame = ttk.Frame(self.root, padding="10")
        main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))

        # 配置网格权重
        self.root.columnconfigure(0, weight=1)
        self.root.rowconfigure(0, weight=1)
        main_frame.columnconfigure(1, weight=1)

        # 标题
        title_label = ttk.Label(main_frame, text="m4s视频音频合并提取器", font=("Arial", 16, "bold"))
        title_label.grid(row=0, column=0, columnspan=3, pady=(0, 20))

        # 视频文件选择
        ttk.Label(main_frame, text="视频文件:").grid(row=1, column=0, sticky=tk.W, pady=5)
        ttk.Entry(main_frame, textvariable=self.video_path).grid(row=1, column=1, sticky=(tk.W, tk.E), padx=(10, 10), pady=5)
        ttk.Button(main_frame, text="浏览...", command=self.browse_video).grid(row=1, column=2, pady=5)

        # 音频文件选择
        ttk.Label(main_frame, text="音频文件:").grid(row=2, column=0, sticky=tk.W, pady=5)
        ttk.Entry(main_frame, textvariable=self.audio_path).grid(row=2, column=1, sticky=(tk.W, tk.E), padx=(10, 10), pady=5)
        ttk.Button(main_frame, text="浏览...", command=self.browse_audio).grid(row=2, column=2, pady=5)

        # 输出文件选择
        ttk.Label(main_frame, text="输出文件:").grid(row=3, column=0, sticky=tk.W, pady=5)
        ttk.Entry(main_frame, textvariable=self.output_path).grid(row=3, column=1, sticky=(tk.W, tk.E), padx=(10, 10), pady=5)
        ttk.Button(main_frame, text="浏览...", command=self.browse_output).grid(row=3, column=2, pady=5)

        # 合并按钮
        self.merge_button = ttk.Button(main_frame, text="合并", command=self.start_merge)
        self.merge_button.grid(row=4, column=0, columnspan=3, pady=20)

        # 进度条
        self.progress = ttk.Progressbar(main_frame, mode='indeterminate')
        self.progress.grid(row=5, column=0, columnspan=3, sticky=(tk.W, tk.E), pady=10)

        # 状态标签
        self.status_label = ttk.Label(main_frame, text="请选择视频和音频文件")
        self.status_label.grid(row=6, column=0, columnspan=3, pady=10)

        # 日志文本框
        self.log_text = tk.Text(main_frame, height=10, state='disabled')
        self.log_text.grid(row=7, column=0, columnspan=3, sticky=(tk.W, tk.E, tk.N, tk.S), pady=10)
        
        # 配置日志文本框的滚动条
        log_scrollbar = ttk.Scrollbar(main_frame, orient="vertical", command=self.log_text.yview)
        log_scrollbar.grid(row=7, column=3, sticky=(tk.N, tk.S))
        self.log_text.configure(yscrollcommand=log_scrollbar.set)
        
        # 配置网格权重
        main_frame.rowconfigure(7, weight=1)
        main_frame.columnconfigure(1, weight=1)

    def browse_video(self):
        filename = filedialog.askopenfilename(
            title="选择视频文件",
            filetypes=[("M4S文件", "*.m4s"), ("所有文件", "*.*")]
        )
        if filename:
            self.video_path.set(filename)
            self.update_status("已选择视频文件")

    def browse_audio(self):
        filename = filedialog.askopenfilename(
            title="选择音频文件",
            filetypes=[("M4S文件", "*.m4s"), ("所有文件", "*.*")]
        )
        if filename:
            self.audio_path.set(filename)
            self.update_status("已选择音频文件")

    def browse_output(self):
        filename = filedialog.asksaveasfilename(
            title="保存输出文件",
            defaultextension=".mp4",
            filetypes=[("MP4文件", "*.mp4"), ("所有文件", "*.*")]
        )
        if filename:
            self.output_path.set(filename)
            self.update_status("已选择输出路径")

    def update_status(self, message):
        self.status_label.config(text=message)
        self.log_message(message)

    def log_message(self, message):
        self.log_text.config(state='normal')
        self.log_text.insert(tk.END, message + "\n")
        self.log_text.config(state='disabled')
        self.log_text.see(tk.END)

    def start_merge(self):
        # 检查输入
        if not self.video_path.get() or not self.audio_path.get():
            messagebox.showerror("错误", "请选择视频文件和音频文件")
            return

        if not self.output_path.get():
            messagebox.showerror("错误", "请选择输出文件路径")
            return

        # 在单独的线程中执行合并操作
        self.merge_button.config(state='disabled')
        self.progress.start()
        self.update_status("正在合并文件...")

        merge_thread = threading.Thread(target=self.merge_files)
        merge_thread.start()

    def merge_files(self):
        try:
            video_file = self.video_path.get()
            audio_file = self.audio_path.get()
            output_file = self.output_path.get()

            # 检查FFmpeg是否可用
            if not self.is_ffmpeg_available():
                self.root.after(0, lambda: messagebox.showerror("错误", "未找到FFmpeg，请确保FFmpeg已安装并在系统路径中"))
                self.root.after(0, self.merge_finished)
                return

            # 使用FFmpeg合并文件
            cmd = [
                'ffmpeg',
                '-i', video_file,
                '-i', audio_file,
                '-c', 'copy',
                output_file,
                '-y'
            ]

            self.log_message("执行命令: " + " ".join(cmd))
            
            # 执行命令
            process = subprocess.Popen(
                cmd,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                universal_newlines=True
            )
            
            # 等待进程完成并获取输出
            stdout, stderr = process.communicate()
            
            if process.returncode == 0:
                self.root.after(0, lambda: self.update_status("合并完成!"))
                self.root.after(0, lambda: messagebox.showinfo("成功", "文件合并成功!"))
                self.log_message("FFmpeg输出: " + stdout)
            else:
                self.root.after(0, lambda: self.update_status("合并失败"))
                self.root.after(0, lambda: messagebox.showerror("错误", "合并失败，请检查文件格式和FFmpeg安装"))
                self.log_message("FFmpeg错误: " + stderr)
                
        except Exception as e:
            self.root.after(0, lambda: self.update_status("合并过程中出现错误"))
            self.root.after(0, lambda: messagebox.showerror("错误", f"合并过程中出现错误: {str(e)}"))
            self.log_message(f"异常: {str(e)}")
            
        finally:
            self.root.after(0, self.merge_finished)

    def is_ffmpeg_available(self):
        try:
            subprocess.run(['ffmpeg', '-version'], 
                         stdout=subprocess.DEVNULL, 
                         stderr=subprocess.DEVNULL)
            return True
        except FileNotFoundError:
            return False

    def merge_finished(self):
        self.progress.stop()
        self.merge_button.config(state='normal')


def main():
    root = tk.Tk()
    app = M4sMergerApp(root)
    root.mainloop()


if __name__ == "__main__":
    main()